<?php
/**
 * Model
 *
 * @package scorpion-magenta
 * @author Nicky van Meurs
 * @copyright 2012
 * @version 1.0
 * @access public
 */
abstract class Model
{

	protected function __construct($properties)
	{
		if ($properties !== false)
		{
			try
			{
				$reflect = new ReflectionObject($this);
				foreach ($reflect->getProperties() as $property)
					$this->{$property->name} = (array_key_exists($property->name, $properties)) ? $properties[$property->name] : null;
			}
			catch (Exception $e)
			{
				die($e->getMessage());
			}
		}
	}

	protected static function getFields()
	{
		static $fields = array ();
		$calledClass = get_called_class();
		if (!array_key_exists($calledClass, $fields))
		{
			$reflectionClass = new ReflectionClass($calledClass);
			$properties = array ();
			foreach ($reflectionClass->getProperties() as $property)
				$properties[] = $property->name;
			$fields[$calledClass] = $properties;
		}
		return $fields[$calledClass];
	}

	protected static function getSelect()
	{
		return "SELECT " . implode(', ', self::getFields()) . " FROM " . self::getTable();
	}

	protected static function getIndex()
	{
		return get_called_class() . 'ID';
	}

	protected static function getTable()
	{
		return strtolower(get_called_class());
	}

	protected function save()
	{
		global $db;
		$fields = self::getFields();
		$replace = "REPLACE INTO " . strtolower(get_called_class()) . "(" . implode(', ', $fields) . ")";
		$function = function ($value)
				{
					return ':' . $value;
				};
		$replace .= " VALUES (" . implode(', ', array_map($function, $fields)) . ")";
		$stmt = $db->prepare($replace);
		foreach ($fields as $field)
			$stmt->bindParam($field, $this->$field);
		$stmt->execute();
	}

	public static function get($id)
	{
		global $db;
		$stmt = $db->prepare(self::getSelect() . " WHERE " . self::getIndex() . "	= :id LIMIT 1");
		$stmt->bindParam(':id', $id, PDO::PARAM_INT);
		$stmt->execute();
		return new static($stmt->fetch(PDO::FETCH_ASSOC));
	}

	public static function getAll()
	{
		global $db;
		$returnData = array ();
		foreach ($db->query(self::getSelect(), PDO::FETCH_ASSOC) as $row)
			$returnData[] = new static($row);
		return $returnData;
	}

	public static function create(Array $properties)
	{
		global $db;
		$properties[self::getIndex()] = ($db->query('SELECT MAX(' . get_called_class() . 'ID) FROM ' . self::getTable())->fetchColumn() + 1);
		$object = new static($properties);
		$object->save();
		return $object;
	}

	public function update(Array $properties)
	{
		foreach ($properties as $key => $value)
			if (property_exists($this, $key))
				$this->$key = $value;
		$this->save();
	}

	public function updateProperty($key, $value)
	{
		if (property_exists($this, $key))
			$this->$key = $value;
		$this->save();
	}

	public function delete()
	{
		global $db;
		$stmt = "DELETE FROM " . self::getTable() . " WHERE " . self::getIndex() . " = :id";
		$stmt = $db->prepare($stmt);
		$stmt->bindParam(':id', $this->{self::getIndex()}, PDO::PARAM_INT);
		$stmt->execute();
		return $stmt->rowCount();
	}

	/**
	 * Getter for some private attributes
	 *
	 * @param mixed $attribute
	 * @return mixed $attribute
	 */
	public function getProperty($attribute)
	{
		return (isset($this->{$attribute})) ? $this->{$attribute} : false;
	}

}

?>